from PyQt5.Qt import *
from PyQt5.QtGui import *
from uiFiles import ui_wifi
import wificonnect
import askDialog
import uiTools
import subprocess
import wifidhcpdialog
import threading
from gtyConfig import language, systemConfig
from gtyTools import gtyLog, gtyTypes


class WifiControl(QDialog, ui_wifi.Ui_wifiDialog):
    def __init__(self, mainPage, eventQ, parent=None):
        super(WifiControl, self).__init__(parent)
        self.sudo_password = systemConfig.passwd
        self.setupUi(self)
        uiTools.centerAndSetIcon(self)
        self.setWindowTitle("WiFi")
        self.mainPage = mainPage
        self.eventQ = eventQ
        self.connectDialog = wificonnect.WifiConnect(self)
        self.askDialog = askDialog.AskDialog(self)
        self.cntButton.clicked.connect(self.connectWifi)
        self.button_dhcp.clicked.connect(self.show_dhcp_dialog)
        self.button_refresh.clicked.connect(self.refresh)
        self.button_hotpot.clicked.connect(self.on_hotpot_button_clicked)
        self.button_hotpot.hide()
        self.configHandlers = gtyTypes.ConfigHandlers()
        self.releaseMode = self.configHandlers.state.read('machine', 'releaseMode')
        if self.releaseMode == "debug":
            self.button_hotpot.show()
            self.check_hotspot_status()
        self.init_tablewidget()
        self.init_language()
        self.show_details()
        threading.Thread(target=self.scan_wifi).start()

    def init_tablewidget(self):
        self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)  # 设置tablewidget不可编辑
        self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)  # 设置整行选择
        self.tableWidget.setColumnCount(2)
        self.tableWidget.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)  # 设置第一列tablewidget拉伸
        self.tableWidget.setColumnWidth(1, 55)
        self.tableWidget.setHorizontalHeaderLabels(['wifi', f'Signal\nStrength'])
        self.tableWidget.verticalHeader().setVisible(False)

    def scan_wifi(self):
        cmd = "nmcli -t -f SSID,SIGNAL device wifi list"
        wifiListObject = self.run_sudo_command(cmd).stdout.splitlines()
        if wifiListObject:
            wifiList = [tuple(line.split(':')) for line in wifiListObject if not line.startswith(':')]
            # 过滤重复wifi
            wifiListUnique = self.uniqueList(wifiList)
            # 将wifi添加到窗口   需要分成两列，一列ssid一列信号
            self.tableWidget.setRowCount(len(wifiListUnique))
            index = 0
            for i in wifiListUnique:
                item1 = QTableWidgetItem(i[0])
                item2 = QTableWidgetItem(str(i[1]))
                font = QFont()
                font.setPointSize(14)
                item1.setFont(font)
                item2.setFont(font)
                self.tableWidget.setItem(index, 0, item1)
                self.tableWidget.setItem(index, 1, item2)
                index += 1

    def run_sudo_command(self, command, **args):
        """运行需要 sudo 权限的命令"""
        if self.sudo_password:
            # 使用 echo 密码 | sudo -S 命令格式
            command = f"echo {self.sudo_password} | sudo -S {command}"
            result = subprocess.run(command, shell=True, stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE, text=True, **args)
            # 检查命令是否成功执行
            if result.returncode == 0:
                return result
        return None

    def hide_password(self):
        if self.connectDialog.checkBox_hide.isChecked():
            self.connectDialog.lineEdit.setEchoMode(QLineEdit.Password)
        else:
            self.connectDialog.lineEdit.setEchoMode(QLineEdit.Normal)

    def connectWifi(self):
        row = self.tableWidget.currentRow()
        self.ssid = self.tableWidget.item(row, 0).text()
        self.connectDialog.label.setText(f" {self.ssid}{language.wifi_connecting_dialog}")
        # 尝试从保存过的密码中获取密码
        saved_passwd = self.check_saved_password(self.ssid)
        self.connectDialog.lineEdit.setText(saved_passwd)
        self.connectDialog.checkBox_hide.setChecked(True)
        self.connectDialog.lineEdit.setEchoMode(QLineEdit.Password)
        self.connectDialog.checkBox_hide.stateChanged.connect(self.hide_password)
        if self.connectDialog.exec() == QDialog.Accepted:
            passwd = self.connectDialog.lineEdit.text()
            self.connectDialog.lineEdit.clear()
            try:
                # 连接wifi
                cmd = f"nmcli device wifi connect '{str(self.ssid)}' "
                if passwd is not None and passwd is not '':
                    cmd += f" password '{str(passwd)}' "
                cmd += f'ifname wlan0'
                result = self.run_sudo_command(cmd, timeout=5)
                if result is not None:
                    if result.returncode == 0:
                        if 'Error' in result.stdout:
                            QMessageBox.warning(self, "Error",
                                                f"check password "
                                                f"and try again\n{result.stdout}")
                        else:
                            QMessageBox.information(self, "Success",
                                                    f"connected to {self.ssid}\n"
                                                    f"{result.stdout}")
                        return
                QMessageBox.warning(self, "Error", "check password and try again")
            except subprocess.TimeoutExpired:
                QMessageBox.warning(self, "Error", "Timeout")
            except Exception as e:
                # 出现错误，记录日志
                gtyLog.log.write(__file__, 'wifi_error', str(e), f"ssid: {self.ssid}", f"passwd: {passwd}")
                QMessageBox.warning(self, "Error", f"{str(e)}")
            self.show_details()
        else:
            # 如果用户取消了对话框，不做任何操作
            return

    def check_saved_password(self, ssid):
        # 构建nmcli命令以获取指定WiFi网络的密码
        command = f" nmcli connection show"
        result = self.run_sudo_command(command).stdout
        connections = result.splitlines()[1:]
        # 初始化新列表
        saved_wifi_ssid = []
        for connection in connections:
            parts = connection.split()
            # 检查连接类型是否为'wifi'
            if parts[-2] == 'wifi':  # 倒数第二元素是连接类型
                connection_name = ' '.join(parts[:-3])  # 拼接wifi名称，用空格分隔
                saved_wifi_ssid.append(connection_name.strip())  # 去除可能的前后空白字符
        gtyLog.log.write(__file__, 'wifi_log', "get saved wifi ssid lst", f"{str(saved_wifi_ssid)}")
        if ssid in saved_wifi_ssid:
            try:
                cmd = f"nmcli connection show '{ssid}' -s | grep 802-11-wireless-security.psk:"
                password_lst = self.run_sudo_command(cmd).stdout.split(':')
                psk = password_lst[1].strip()
                if password_lst[0] == 'Error' or psk == '--':
                    return ''
                gtyLog.log.write(__file__, 'wifi_log', "get saved wifi password", f"{psk}")
                return psk
            except Exception as e:
                gtyLog.log.write(__file__, 'wifi_error', "get saved wifi password error", f"{str(e)}")
        return ''

    # 用于过滤扫描到的重复wifi
    def uniqueList(self, list1):
        # 用一个集合来过滤
        seen = set()
        unique_list = []
        for item in list1:
            name = item[0]
            if name not in seen:
                seen.add(name)
                unique_list.append(item)
        return unique_list

    def show_details(self):
        details_dict = {}
        try:
            cmd2 = "nmcli device show wlan0"
            lsttmp = self.run_sudo_command(cmd2).stdout.splitlines()
            result = {}
            for line in lsttmp:
                if ':' in line:
                    key, value = line.split(':', 1)
                    key = key.strip()
                    value = value.strip()
                    result[key] = value
            if result:
                # 提取常用信息
                if 'GENERAL.DEVICE' in result:
                    details_dict['device'] = result['GENERAL.DEVICE']
                if 'GENERAL.TYPE' in result:
                    details_dict['type'] = result['GENERAL.TYPE']
                if 'GENERAL.STATE' in result:
                    details_dict['state'] = result['GENERAL.STATE']
                if 'GENERAL.CONNECTION' in result:
                    details_dict['connection'] = result['GENERAL.CONNECTION']
                if 'IP4.ADDRESS' in str(result):
                    # 处理 IP4.ADDRESS[1] 这种格式的键
                    address_keylst = [k for k in result.keys() if k.startswith('IP4.ADDRESS')]
                    if address_keylst:
                        addresses = [result[key] for key in address_keylst]
                        details_dict['ip[1]'] = addresses[0].split('/')[0] if addresses else ''
                        details_dict['ip[2]'] = addresses[1].split('/')[0] if len(addresses) > 1 else ''
                        # 从 IP 地址后的斜杠后面提取子网掩码
                        subnet_mask = self.calculate_subnet_mask(int(addresses[0].split('/')[1])) if addresses else ''
                        details_dict['mask[1]'] = subnet_mask
                        subnet_mask2 = self.calculate_subnet_mask(int(addresses[1].split('/')[1])) if len(
                            addresses) > 1 else ''
                        details_dict['mask[2]'] = subnet_mask2
                if 'IP4.GATEWAY' in result:
                    details_dict['gateway'] = result['IP4.GATEWAY']
                if 'IP4.DNS' in str(result):
                    # 处理 IP4.DNS[1] 这种格式的键
                    dns_key = [k for k in result.keys() if k.startswith('IP4.DNS')]
                    if dns_key:
                        dnses = [result[key] for key in dns_key]
                        details_dict['dns'] = ', '.join(dnses)
                if 'IP4.ROUTE' in str(result):
                    # 处理 IP4.ROUTE[1] 等路由信息
                    route_keys = [k for k in result.keys() if k.startswith('IP4.ROUTE')]
                    if route_keys:
                        routes = [result[key] for key in route_keys]
                        details_dict['routing_info'] = ',\n'.join(routes)

            else:
                gtyLog.log.write(__file__, 'wifi_error', "No result obtained", f'\n{str(result)}')
        except Exception as e:
            gtyLog.log.write(__file__, 'wifi_error', str(e))
            QMessageBox.warning(self, "Error", f"Failed to obtain network information,{str(e)}")
            details_dict['error'] = str(e)
        # 显示wifi信息
        wifi_info = "WIFI INFO："
        for key, value in details_dict.items():
            if key == 'error':
                continue
            wifi_info += f"\n{key}: {value}"
        self.textEdit_ip.setText(wifi_info)
        return details_dict

    def calculate_subnet_mask(self, prefix_length):
        # 计算子网掩码的函数
        mask = [0, 0, 0, 0]
        for i in range(prefix_length):
            index = i // 8
            shift = 7 - (i % 8)
            mask[index] += 1 << shift
        return '.'.join(map(str, mask))

    def show_dhcp_dialog(self):
        w = wifidhcpdialog.myUI(self)
        w.init_wifi_info(self.show_details())
        w.exec()

    def refresh(self):
        self.show_details()
        self.scan_wifi()

        return None

    def check_hotspot_status(self):
        """检查热点是否正在运行"""
        result = subprocess.run("nmcli connection show --active", shell=True, stdout=subprocess.PIPE)
        active_connections = result.stdout.decode('utf-8')

        # 如果 Hotspot 存在于活动连接中，返回 True，表示已打开
        if "Hotspot" in active_connections:
            self.button_hotpot.setText("热点：开")
            return True
        else:
            self.button_hotpot.setText("热点：关")
            return False

    def hotpot_set(self):

        if self.check_hotspot_status():
            self.run_sudo_command(" nmcli connection down Hotspot")
            self.run_sudo_command("sudo ifconfig wlan0 down")
            self.run_sudo_command("sudo ifconfig wlan0 up")
            self.run_sudo_command("nmcli connection delete Hotspot")
        else:
            # 删除已有 Hotspot 连接
            self.run_sudo_command("nmcli connection delete Hotspot")
            # 重新设置热点
            self.run_sudo_command("bash /home/feibot/cmds/start_hotpot.sh")

            # 锁定 wlan0，防止系统抢占
            # self.run_sudo_command("sudo nmcli device set wlan0 managed no")

    def on_hotpot_button_clicked(self):
        # 创建并启动线程
        thread = threading.Thread(target=self.hotpot_set)
        thread.start()

    def init_language(self):
        self.button_dhcp.setText(language.wifi_static_ip_and_dhcp)
        self.cntButton.setText(language.wifi_connect)
        self.pushButton.setText(language.wifi_back)
        self.button_refresh.setText(language.wifi_refresh)
